package rollercoaster.environment.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

import rollercoaster.environment.interfaces.IModelReader;
import rollercoaster.environment.interfaces.IObjFileReader;
import rollercoaster.commons.Vertex2D;
import rollercoaster.commons.Vertex3D;

public class OBJFileModelReader implements IObjFileReader  {

	
	private ArrayList<Vertex3D> vertices;
	private ArrayList<Vertex3D> normals;
	private ArrayList<Vertex2D> texCoord;
	private ArrayList<ObjFace> faces;
	
	private String filepath;
	private HashMap<String, Integer> geometries;
	private HashMap<String, ArrayList<ObjFace>> listModels;
	private String geometryName;
	
		
	public void setFilepath(String filepath) {
		this.filepath = filepath;
		getFromFile();
	}



	private void getFromFile(){
		
	//	OBJFileModelReader obj = new OBJFileModelReader();
		
		
		try {
					
			BufferedReader reader=new BufferedReader(new FileReader(new File(filepath)));
			
			vertices=new ArrayList<Vertex3D>();
			normals=new ArrayList<Vertex3D>();
			texCoord=new ArrayList<Vertex2D>();
			listModels=new HashMap<String, ArrayList<ObjFace>>();
			faces=new ArrayList<ObjFace>();
			
			String line=reader.readLine();

			while(line!=null){
				StringTokenizer tok=new StringTokenizer(line," ");
				if(tok.hasMoreTokens()){
					String identifier=tok.nextToken().trim();
					if(identifier.equalsIgnoreCase("v")){
						addVertex3DToList(vertices,tok);
					}
					if(identifier.equalsIgnoreCase("vn")){
						addVertex3DToList(normals,tok);
					}
					if(identifier.equalsIgnoreCase("vt")){
						addVertex2DToList(texCoord,tok);

					}
					if(identifier.equalsIgnoreCase("f")){
						addObjFaceToList(faces,tok);
					}
					if(identifier.equalsIgnoreCase("g")){
						addGeometry(tok);
					}
				}
				line=reader.readLine();

				}
			
			//System.out.println("Numero facce nell obj"+faces.size());

			if(listModels.get(geometryName)!=null){
				listModels.get(geometryName).addAll(faces);
			}
			else{			
			ArrayList<ObjFace> newFaces= new ArrayList<ObjFace>(faces);
			listModels.put(geometryName, newFaces);
			}
			
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}



	}

	
	private void addGeometry(
			StringTokenizer tok) {
		if(faces.size()!=0){
			if(listModels.get(geometryName)!=null){
				listModels.get(geometryName).addAll(faces);
			}
			else{			
			ArrayList<ObjFace> newFaces= new ArrayList<ObjFace>(faces);
			listModels.put(geometryName, newFaces);
			}
			geometryName=tok.nextToken();
			faces.clear();

		}
		else{
			geometryName=tok.nextToken();
			
		}
	}



	public String getGeometryName() {
		return geometryName;
	}



	public void setGeometryName(String geometryName) {
		this.geometryName = geometryName;
	}



	private static void addVertex3DToList(ArrayList<Vertex3D> list,StringTokenizer tok){

		list.add(new Vertex3D(new Float(tok.nextToken()).floatValue(), new Float(tok.nextToken()).floatValue(), new Float(tok.nextToken()).floatValue()));
	}
	private static void addVertex2DToList(ArrayList<Vertex2D> list,StringTokenizer tok){

		list.add(new Vertex2D(new Float(tok.nextToken()).floatValue(), new Float(tok.nextToken()).floatValue()));
	}
	
	private static void addObjFaceToList(ArrayList<ObjFace> face,StringTokenizer tok){
					
			int size=tok.countTokens();
			
			int vertex[]=new int[size];
			int normals[]=new int[size];
			int texCoord[]=new int[size];
			
			int index=0;
			
			while(tok.hasMoreElements()){
				
				String token=tok.nextToken();

	            char c[]=token.toCharArray();
	            int id1=-1;
	            int id2=-1;
	            for(int j=0;j<c.length;j++){
					if(c[j]=='/'){
						id1=j;
						j=c.length;
					}
				}
				if(id1!=-1){
					for(int j=id1+1;j<c.length;j++){
						if(c[j]=='/'){
							id2=j;
							j=c.length;
						}
					}
				}

	            if(id1==-1){
	            	vertex[index]=new Integer(token);
				}else{
					vertex[index]=new Integer(token.substring(0,id1));

					if(id2!=-1){
	                    if(id2>id1+1){
	                    	texCoord[index]=new Integer(token.substring(id1+1,id2));
						}
	                    normals[index]=new Integer(token.substring(id2+1,token.length()));
					}else{
						texCoord[index]=new Integer(token.substring(id1+1,token.length()));
					}
				}
				
				index++;
			}
			//System.out.println(vertex[0] +"/"+normals[0]+"/"+texCoord[0]+"/n");
			ObjFace fac=new ObjFace(vertex,normals,texCoord);
			face.add(fac);
			
	}
	
	
	
	
	
	public ArrayList<Vertex3D> getVertices() {
		// TODO Auto-generated method stub
		return vertices;
	}

	public float[] getVerticesArray(){
		float[] verticesArray = new float[vertices.size()*3];
		for (int i = 0; i < vertices.size(); i++) {
			verticesArray[3*i]=vertices.get(i).getX();
			verticesArray[3*i+1]=vertices.get(i).getY();
			verticesArray[3*i+2]=vertices.get(i).getZ();

		}
		return verticesArray;
	}
	public float[] getNormalsArray(){
		float[] normalsArray = new float[normals.size()*3];
		for (int i = 0; i < normals.size(); i++) {
			normalsArray[3*i]=normals.get(i).getX();
			normalsArray[3*i+1]=normals.get(i).getY();
			normalsArray[3*i+2]=normals.get(i).getZ();

		}
		return normalsArray;
	}
	public ArrayList<Vertex3D> getNormals() {
		// TODO Auto-generated method stub
		return normals;
	}

	public ArrayList<Vertex2D> getTexCoord() {
		// TODO Auto-generated method stub
		return texCoord;
	}
	


	public ArrayList<ObjFace> getFaces() {
		return faces;
	}
	
	public ArrayList<ObjFace> getFacesGeometry(String gName){
		
		return listModels.get(gName);  
	}
	
	



	public HashMap<String, ArrayList<ObjFace>> getListModels() {
		System.out.println("dimensione lista : "+listModels.size());
		return listModels;
	}



	public void setFaces(ArrayList<ObjFace> faces) {
		this.faces = faces;
	}
	
	



}
